﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Threading;
using Microsoft.Win32;
using System.Configuration;

namespace SynchronizedPlayer {
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window {
		private MyMediaPlayer player = new MyMediaPlayer();
		private VideoDrawing video = new VideoDrawing();
		private DrawingBrush videoDrawingBrush;
		private string filter = "Mp3 files (*.mp3)|*.mp3| AVI files (*.avi)|*.avi| MKV files (*.mkv)|*.mkv";
		private DispatcherTimer _timer = new DispatcherTimer();
		private Playlist currentPlaylist = new Playlist();
		private Controller netController;
		private List<String> videoExtensions = new List<string> { ".avi", ".mkv" };

		private const int VIDEO_MODE_HEIGHT = 645;
		private const int AUDIO_MODE_HEIGHT = 230;
		private const string NULL_TIME = "00:00:00";

		private int currentTrackIndex = 0;
		private bool update = false;

		private int trackIndex;
		private double trackPosition;


		public MainWindow() {
			InitializeComponent();

			video.Rect = new Rect(0, 0, 300, 100);
			video.Player = player;
			videoDrawingBrush = new DrawingBrush(video);
			VideoPanel.Background = videoDrawingBrush;

			playlist.SelectionMode = SelectionMode.Single;

			KeyValueConfigurationCollection settings = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings;

			player.MediaOpened += player_MediaOpened;
			netController = new Controller(int.Parse(settings["Port"].Value), settings["IP"].Value, int.Parse(settings["Port"].Value));
			netController.Subscribe(typeof(CMDPlaylistBegin), synchCallback);

			

			this.Closing += MainWindow_Closing;

			mediaProgress.Foreground = Brushes.Red;
			_timer.Interval = TimeSpan.FromMilliseconds(1000);
			_timer.Tick += new EventHandler(ticktock);
			_timer.Start();
		}

		void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
			netController.Dispose();
		}

		private void ticktock(object sender, EventArgs e) {
			mediaProgress.Value = player.Position.TotalSeconds;


			if (update && currentPlaylist.Count != 0) {
				playlist.ItemsSource = currentPlaylist;
				playlist.SelectedIndex = trackIndex;
				startPlaying((playlist.SelectedItem as PlaylistItem).path);
				player.Position = TimeSpan.FromSeconds(trackPosition);
				update = false;
			}
			if (player.isStarted) {
				timeText.Text = player.Position.ToString();
			}
		}

		private void player_MediaOpened(object sender, EventArgs e) {
			mediaProgress.Minimum = 0;
			mediaProgress.Maximum = player.NaturalDuration.TimeSpan.TotalSeconds;
		}

		private bool isVideo(string path) {
			foreach (string ext in videoExtensions) {
				if (path.EndsWith(ext)) {
					return true;
				}
			}
			return false;
		}

		private void playButtonClicked(object sender, RoutedEventArgs e) {
			if (player.isPlaying) {
				return;
			}

			if (player.isPaused) {
				player.Play();
			} else {
				playSelectedTrack();
			}
		}

		private void pauseButtonClicked(object sender, RoutedEventArgs e) {
			if (player.isPlaying) {
				player.Pause();
			}
		}

		private void startPlaying(string path) {
			if (isVideo(path)) {
				this.Height = VIDEO_MODE_HEIGHT;
			} else {
				this.Height = AUDIO_MODE_HEIGHT;
			}
			
			currentTrackIndex = playlist.SelectedIndex;
			VideoPanel.Background = videoDrawingBrush;
			titleText.Text = (playlist.SelectedItem as PlaylistItem).displayName;

			player.Open(new Uri(path, UriKind.Absolute));
			player.Position = TimeSpan.FromSeconds(0);
			player.Play();
		}

		private void stopButtonClicked(object sender, RoutedEventArgs e) {
			stopPlaying();
		}

		private void stopPlaying() {
			player.Stop();
			this.Height = AUDIO_MODE_HEIGHT;
			titleText.Text = string.Empty;
			timeText.Text = NULL_TIME;
		}

		private void addPlaylistItemsClicked(object sender, RoutedEventArgs e) {
			OpenFileDialog dialog = new OpenFileDialog();
			dialog.Filter = filter;
			dialog.Multiselect = true;

			Nullable<bool> result = dialog.ShowDialog();

			if (result == true) {
				currentPlaylist.add(dialog.FileNames);
				if (playlist.ItemsSource == currentPlaylist) {
					playlist.Items.Refresh();
				} else {
					playlist.ItemsSource = currentPlaylist;
				}
			}
		}

		private void playlistItemChosen(object sender, MouseButtonEventArgs e) {
			UIElement elem = (UIElement)playlist.InputHitTest(e.GetPosition(playlist));
			if (elem is TextBlock) {
				startPlaying(currentPlaylist.getPath(((TextBlock)elem).Text));
			}
		}

		private void progressBarClicked(object sender, MouseButtonEventArgs e) {
			if (player.isStarted) {
				Point pos = e.GetPosition(mediaProgress);
				int seconds = (int)(pos.X * mediaProgress.Maximum / mediaProgress.ActualWidth);
				mediaProgress.Value = seconds;
				player.Position = TimeSpan.FromSeconds(seconds);
			}
		}

		private void synchButtonClicked(object sender, RoutedEventArgs e) {
			if (!player.isStarted) {
				netController.SendPlaylist(currentTrackIndex.ToString(), "0", currentPlaylist.getHashes());
			} else {
				netController.SendPlaylist(currentTrackIndex.ToString(), ((int)player.Position.TotalSeconds).ToString(), currentPlaylist.getHashes());
			}
			//netController = new Controller();
		}

		private void synchCallback(object[] data) {
			trackIndex = (int)data[0];
			trackPosition = (double)data[1];
			currentPlaylist = Playlist.create(((List<string>)(data[2])).ToArray());
			update = true;
		}

		private void listBoxKeyPressed(object sender, KeyEventArgs e) {
			if (playlist.SelectedIndex != -1) {
				if (e.Key == Key.Enter) {
					playSelectedTrack();
				} else if (e.Key == Key.Delete) {
					removeSelectedTrack();
				}
			}
		}

		private void removeSelectedTrack() {
			if (playlist.SelectedIndex != -1) {
				int selectedIndex = playlist.SelectedIndex;

				currentPlaylist.remove(selectedIndex);
				if (selectedIndex == currentTrackIndex) {
					currentTrackIndex = 0;
					stopPlaying();
				} else if (selectedIndex < currentTrackIndex) {
					currentTrackIndex--;
				}

				playlist.Items.Refresh();
				playlist.SelectedIndex = -1;
			}
		}

		private void removePlaylistItemClicked(object sender, RoutedEventArgs e) {
			removeSelectedTrack();
		}

		private void playSelectedTrack() {
			if (playlist.SelectedIndex != -1) {
				startPlaying((playlist.SelectedItem as PlaylistItem).path);
			}
		}

		private void previousTrackButtonClicked(object sender, RoutedEventArgs e) {
			if (playlist.Items.Count != 0) {
				currentTrackIndex--;
				if (currentTrackIndex == -1) {
					currentTrackIndex = playlist.Items.Count - 1;
				}
				playlist.SelectedIndex = currentTrackIndex;
				playSelectedTrack();
			}
		}

		private void nextTrackButtonClicked(object sender, RoutedEventArgs e) {
			if (playlist.Items.Count != 0) {
				currentTrackIndex = (currentTrackIndex + 1) % playlist.Items.Count;
				playlist.SelectedIndex = currentTrackIndex;
				playSelectedTrack();
			}
		}

		private void exitButtonClicked(object sender, RoutedEventArgs e) {
			this.Close();
		}

		private void settingsButtonClicked(object sender, RoutedEventArgs e) {
			SettingsWindow settingsWindow = new SettingsWindow();
			settingsWindow.ShowDialog();
			//KeyValueConfigurationCollection settings = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings;
			//netController.Setup(int.Parse(settings["Port"].Value), settings["IP"].Value, int.Parse(settings["Port"].Value));
			//netController.Dispose();
			//netController = new Controller(int.Parse(settings["Port"].Value), settings["IP"].Value, int.Parse(settings["Port"].Value));
		}

		private void aboutButtonClicked(object sender, RoutedEventArgs e) {
			MessageBox.Show("Synchronized Player for SPb AU DevDays", "About", MessageBoxButton.OK, MessageBoxImage.Information);
		}

		private void clearPlaylistClicked(object sender, RoutedEventArgs e) {
			currentPlaylist.Clear();
			playlist.Items.Refresh();
		}

	}
}
